;
; Copyright (c) Microsoft Corporation.  All rights reserved.
;
;
; Use of this source code is subject to the terms of the Microsoft end-user
; license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
; If you did not accept the terms of the EULA, you are not authorized to use
; this source code. For a copy of the EULA, please see the LICENSE.RTF on your
; install media.
;

    INCLUDE kxarm.h
    INCLUDE armmacros.s

    INCLUDE AK_base_regs.inc

    IMPORT  main
    IMPORT  ChipInit
    IMPORT  FillVectors



; ARM processor modes
USER_MODE   EQU 2_10000
FIQ_MODE    EQU 2_10001
IRQ_MODE    EQU 2_10010
SVC_MODE    EQU 2_10011
ABORT_MODE  EQU 2_10111
UNDEF_MODE  EQU 2_11011
SYSTEM_MODE EQU 2_11111

;-------------------------------------------------------------------------------

        TEXTAREA

        

; Set up the MMU and Dcache for bootloader.
;
; This routine will initialize the first-level page table based up the contents
; of the MemoryMap array and enable the MMU and caches.
;
; Copy the image to RAM if it's not already running there.
;
; Include Files 



; Defines 
;------------------------------------------------------------------------------

; External Variables 

; External Functions 

; Global Variables 
 
; Local Variables 
 
; Local Functions 

;-------------------------------------------------------------------------------
;   Function: Startup
;
;   Main entry point for CPU initialization.
;

        STARTUPTEXT
        LEAF_ENTRY      StartUp

        b       ResetHandler

        ; Power-off the CPU. 
        str     r1, [r0]                        ; enable SDRAM self-refresh.
        str     r3, [r2]                        ; MISCCR setting.
        str     r5, [r4]                        ; POWER OFF!!!!!
        b       .
    
ResetHandler

; Make sure that TLB & cache are consistent
        mov     r0, #0
        mcr     p15, 0, r0, c8, c6, 0           ; flush D TLB
        mcr     p15, 0, r0, c8, c5, 0           ; flush I TLB
        mcr     p15, 0, r0, c7, c5, 0           ; flush instruction cache
        mcr     p15, 0, r0, c7, c6, 0           ; flush data cache

;soft reset and disable all module except sdram
        ldr     r1,=0x1bfffbff                  ; except ram module
        ldr     r0,=0x0800000c
        str     r1,[r0]
        ldr     r1,=0xfbff                  ; change module out of reset state
        str     r1,[r0]
        nop
        nop
        nop
        nop
;power managment
        ;enable module
        ldr     r1,=0xdbd7                  ;;open nand sdram usb lcd
        ldr     r0,=0x0800000c
        str     r1,[r0]

;dislable all interrupt
        ldr     r0,=0x08000034
        ldr     r1,=0
        str     r1, [r0]
        ldr     r0,=0x0800004c
        str     r1, [r0]
;mask all FIQ       
        ldr     r0,=0x08000038
        str     r1, [r0]
        
        ;config sharepin reg, do it in main
        ;64M RAM    can not set twice,so nandboot set this before  
        
        ;;reset module, except sdram
        ldr     r0,=0x0800000c
        ldr     r1,[r0]
        ldr     r2,=0xfbff0000
        orr     r1,r1,r2
        str     r1,[r0]     
        ;;wait the reset ok
        ldr r1, =5000
wait
        subs r1, r1, #1
        bne wait
        ldr     r1,[r0]
        ldr     r2,=0x0000ffff
        and     r1,r1,r2
        str     r1,[r0]

;clear ram, for 64M     
;       ldr   r0, = 0x300B8000
;       ldr   r1, = 0x0
;loop_clean     
;       str   r1, [r0], #4
;       add   r0, r0, #4
;       cmp   r0, #0x34000000
;       bne   loop_clean
;------------------------------------------------------------------------------
;   Copy boot loader to memory

        ; Now that we've copied ourselves to RAM, jump to the RAM image.  Use the "CodeInRAM" label
        ; to determine the RAM-based code address to which we should jump.
    
20      add     r2, pc, #CODEINRAM-(.+8)            ; Calculate the relative offset to the 'CodeInRAM' label.
        ldr     r1, =0x0                            ; Get the RAM address to which we copied ourself.
        add     r1, r1, r2                          ; Calculate the RAM address of the 'CodeInRAM' label.
        mov     pc, r1                              ;
        nop
        nop
        nop

        INCLUDE oemaddrtab_cfg.inc

CODEINRAM

; We're now running in SDRAM.

; Compute physical address of the OEMAddressTable.
        add     r11, pc, #g_oalAddressTable - (. + 8)
;;;        ldr     r10, =PTs                           ; (r10) = 1st level page table
        ;
        ; assume the first entry is ram
        add    r0, r11, #4      ;
        ldr     r1, [r0], #4            ; (r1) = physical address to map from
        ldr     r2, [r0], #4                ; (r2) = num MB to map
        mov r2, r2,  LSL #20    ; (r2) = size of ram
        add r12, r1, r2         ; r12 the end of physical ram
        sub     r10, r12, #(4096*4) ; r10 the first lever page table

        ; Setup map of the virtual last 1M
        ldr r0, =((4096-1)*4)
        add r0, r0, r10         ; r0 the addr of the last pt entry
        ldr     r3, =0xFFF00000
        and   r3, r10, r3               ; r3 last pt entry physical addr part
        mov  r4, #0x0E                  ; cachable bufferable,CB =11
        orr    r4, r4, #0x400       ; set kernel r/w permission,set AP =01
        orr r3, r3, r4          ;
        str    r3, [r0]         ; last 1M page table entry

; Setup 1st level page table (using section descriptor)     
; Fill in first level page table entries to create "un-mapped" regions
; from the contents of the MemoryMap array.
;
;   (r10) = 1st level page table
;   (r11) = ptr to MemoryMap array

        add     r10, r10, #0x2000       ; (r10) = ptr to 1st PTE for "unmapped space",0x80000000-0xFFFFFFFF
        mov     r0, #0x0E               ; (r0) = PTE for 0: 1MB cachable bufferable,CB =11
;;;       mov     r0, #0x0A               ; (r0) = PTE for 0: 1MB cachable bufferable,CB =10  write throuth
;;;        mov     r0, #0x02               ; (r0) = PTE for 0: 1MB cachable bufferable,CB =00  no cach no buffer
        orr     r0, r0, #0x400          ; set kernel r/w permission,set AP =01
25      mov     r1, r11                 ; (r1) = ptr to MemoryMap array

        
30      ldr     r2, [r1], #4            ; (r2) = virtual address to map Bank at
        ldr     r3, [r1], #4            ; (r3) = physical address to map from
        ldr     r4, [r1], #4            ; (r4) = num MB to map

        cmp     r4, #0                  ; End of table?
        beq     %f40

        ldr     r5, =0x1FF00000
        and     r2, r2, r5              ; VA needs 512MB, 1MB aligned.                

        ldr     r5, =0xFFF00000
        and     r3, r3, r5              ; PA needs 4GB, 1MB aligned.

        add     r2, r10, r2, LSR #18
        add     r0, r0, r3              ; (r0) = PTE for next physical page,descriptor's value ;section table entry value

35      str     r0, [r2], #4            ; r2?
        add     r0, r0, #0x00100000     ; (r0) = PTE for next physical page
        sub     r4, r4, #1              ; Decrement number of MB left 
        cmp     r4, #0
        bne     %b35                    ; Map next MB

        bic     r0, r0, #0xF0000000     ; Clear Section Base Address Field
        bic     r0, r0, #0x0FF00000     ; Clear Section Base Address Field
        b       %b30                    ; Get next element
        
40      tst     r0, #8
        bic     r0, r0, #0x0C           ; clear cachable & bufferable bits in PTE
        add     r10, r10, #0x0800       ; (r10) = ptr to 1st PTE for "unmapped uncached space",0xA0000000
        bne     %b25                    ; go setup PTEs for uncached space
        sub     r10, r10, #0x3000       ; (r10) = restore address of 1st level page table,need test?duke can it be?


; Setup the vector area.
;
;       (r8) = ptr to exception vectors
        sub r8, r12, #0x10000

        add     r7, pc, #VectorInstructions - (.+8)
        ldmia   r7!, {r0-r3}                    ; load 4 instructions
        stmia   r8!, {r0-r3}                    ; store the 4 vector instructions
        ldmia   r7!, {r0-r3}                    ; load 4 instructions
        stmia   r8!, {r0-r3}                    ; store the 4 vector instructions
    ;; fill the real vector juct after vectors after mmu enable

;        ldr     r10, =PTs                  ; (r10) = restore address of 1st level page table
        sub     r10, r12, #(4096*4)     ; r10 the first lever page table
; The page tables and exception vectors are setup.
; Initialize the MMU and turn it on.
        mov     r1, #1
        mcr     p15, 0, r1, c3, c0, 0       ; setup access to domain 0
        mcr     p15, 0, r10, c2, c0, 0  ; set page table base reg
        
        mov     r0, #0
        mcr     p15, 0, r0, c8, c6, 0   ; flush D TLB
        mcr     p15, 0, r0, c8, c5, 0   ; flush I TLB
        
        mov     r1, #0x0073             ; Enable: MMU Alignment fault, Bits [6:3] must be written as 1's.
        orr     r1, r1, #0x4            ; Enable DC.
        orr     r1, r1, #0x1000         ; Enable IC.
        orr     r1, r1, #0x2000         ; high vector.

        ldr     r0, =VirtualStart
        cmp     r0, #0                  ; make sure no stall on "mov pc,r0" below
        mcr     p15, 0, r1, c1, c0, 0
        mov     pc, r0                  ;  & jump to new virtual address
        nop

; MMU & caches now enabled.
;   (r10) = physcial address of 1st level page table
;

VirtualStart

; Initialize stacks for each mode.
        ; the last 1M used as stack 
        ldr r0, =0xfff00000 

        mov     r1, #ABORT_MODE:OR:0xC0
        msr     cpsr_c, r1                      ; switch to Abort Mode w/IRQs disabled
        add     sp, r0, #0x30000

        mov     r1, #IRQ_MODE:OR:0xC0
        msr     cpsr_c, r1                      ; switch to IRQ Mode w/IRQs disabled
        add     sp, r0, #0x60000

        mov     r1, #FIQ_MODE:OR:0xC0
        msr     cpsr_c, r1                      ; switch to FIQ Mode w/IRQs disabled
        add     sp, r0, #0x90000

        mov     r1,  #UNDEF_MODE:OR:0xC0
        msr     cpsr_c, r1                      ; switch to Undefined Mode w/IRQs disabled
        add     sp, r0, #0xc0000

        mov     r1, #SVC_MODE:OR:0xC0
        msr     cpsr_c, r1                      ; switch to Supervisor Mode w/IRQs disabled
        add     sp, r0, #0xf0000

        ;fill the real vector juct after vectors
        ldr r0, =(0xffff0000+0x20)
        CALL FillVectors

        ldr r0, =g_oalAddressTable
        CALL    ChipInit

;;;        mov     r0, #SVC_MODE       ; switch to Supervisor Mode w/IRQs enabled
        mov     r0, #SYSTEM_MODE
        msr     cpsr_c, r0                      ; switch to Supervisor Mode w/IRQs enabled
    ; svc use user special stack
        mov     sp, #0x80000000
        add     sp, sp, #0xd0000        ; arbitrary initial super-page stack pointer

        b       main

        ENTRY_END

VectorInstructions
        ldr     pc, [pc, #0x20-8]              ; reset
        ldr     pc, [pc, #0x20-8]              ; undefined instruction
        ldr     pc, [pc, #0x20-8]              ; SVC
        ldr     pc, [pc, #0x20-8]              ; Prefetch abort
        ldr     pc, [pc, #0x20-8]              ; data abort
        ldr     pc, [pc, #0x20-8]              ; unused vector location
        ldr     pc, [pc, #0x20-8]              ; IRQ
        ldr     pc, [pc, #0x20-8]              ; FIQ



        LEAF_ENTRY OALFlushICache

        mov     r0, #0
        mcr     p15, 0, r0, c7, c5, 0

        RETURN


        LEAF_ENTRY OALFlushDCache

        ; Test, clean and invalidate entire data cache
10      mrc p15, 0, r15, c7, c14, 3
        bne %b10

        RETURN

        LEAF_ENTRY OALCleanDCache

        ; Test and clean entire data cache
10      mrc p15, 0, r15, c7, c10, 3
        bne %b10

        RETURN

;VOID OALFlushICacheLines( VOID *pAddress, UINT32 size);
        LEAF_ENTRY OALFlushICacheLines

;        ldr     r2, =g_oalCacheInfo
;        ldr     r3, [r2, #L1ILineSize]
    mov r3, #32             ; 7801 line size is 32

10      mcr     p15, 0, r0, c7, c5, 1           ; invalidate entry
        add     r0, r0, r3                      ; move to next
        subs    r1, r1, r3
        bgt     %b10                            ; loop while > 0 bytes left

        RETURN

        END

        LTORG


    NOP
    NOP
    NOP
        
        END

;-------------------------------------------------------------------------------        
